////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
//  File name:   brushface.h
//  Version:     v1.00
//  Created:     8/7/2002 by Timur.
//  Compilers:   Visual Studio.NET
//  Description: 
// -------------------------------------------------------------------------
//  History: Based on Andrey's Indoor editor.
//  02/03/2010 Refactored by Jaesik.
////////////////////////////////////////////////////////////////////////////

#ifndef __BRUSHFACE_H__
#define __BRUSHFACE_H__

#if _MSC_VER > 1000
#pragma once
#endif

#include "brushplane.h"
#include "brushcommon.h"

struct SBrushVertex
{
	SBrushVertex( const Vec3& _pos )	:
		pos(_pos),
		bSelected(0)
		
	{
		st[0] = 0;
		st[1] = 0;
	}

	SBrushVertex() :
		pos(0,0,0),
		bSelected(0)
	{
		st[0] = 0;
		st[1] = 0;
	}
 
	~SBrushVertex()
	{
	}
	
	int GetMemorySize();

	Vec3  pos;
	float st[2];
	bool bSelected;
};

struct SBrushTriangle
{
	SBrushTriangle()
		:	faceidx(SBrushCommon::VertexFaceMax),
			normal(0,1,0)
	{
		for( int i = 0; i < 3; i++ )
		{
			vertexindices[i] = SBrushCommon::VertexFaceMax;
			adjacentfidx[i] = SBrushCommon::VertexFaceMax;
		}
		boundbox.Reset();
	}

	bool SetVertexIndices(	const std::vector<SBrushVertex*>& vtxlist, 
													SBrushCommon::VertexFaceIndexType i0, 
													SBrushCommon::VertexFaceIndexType i1, 
													SBrushCommon::VertexFaceIndexType i2, 
													SBrushCommon::VertexFaceIndexType fidx );
	bool SetVertexIndices(	const Vec3& v0, const Vec3& v1, const Vec3& v2, 
													SBrushCommon::VertexFaceIndexType i0, 
													SBrushCommon::VertexFaceIndexType i1, 
													SBrushCommon::VertexFaceIndexType i2, 
													SBrushCommon::VertexFaceIndexType fidx );

	void CalcBound( const std::vector<SBrushVertex*>& vtxlist );
	void CalcBound( const Vec3& v0, const Vec3& v1, const Vec3& v2 );
	void Invert();

	int GetMemorySize();


private:

	friend struct SBrush;
	friend struct SBrushFace;
	friend class	CBrushSerialize;

	SBrushCommon::VertexFaceIndexType	vertexindices[3];
	SBrushCommon::VertexFaceIndexType	adjacentfidx[3];
	SBrushCommon::VertexFaceIndexType	faceidx;
	AABB	boundbox;
	Vec3	normal;
};

struct SBrushFace
{
	SBrushFace() : 
		matID(0),
		bSelected(false),
		selectededge(0)
	{
	}

	void MakePlane( const std::vector<SBrushVertex*>& vtxlist, int triIndex0, int triIndex1, int triIndex2 );

	void CalcTexCoords( SBrushVertex& v );
	const Vec3& GetCenter()	{	return center;	}
	void CalcCenter( const std::vector<SBrushVertex*>& vtxlist );
	void CalcPlane( const std::vector<SBrushVertex*>& vertexlist );

	void MapEdgeIndexToPolyIndices( const std::vector<SBrushVertex*>& vtxlist,  
																	const std::vector<SBrushTriangle*>& trilist, 
																	const int& nEdgeIndex,
																	int &rnFirstPolyVertex, 
																	int& rnSecondPolyVertex ) const;

	void CalcBound( const std::vector<SBrushVertex*>& vtxlist, Vec3& mins, Vec3& maxs );
	void CalcBound( const std::vector<SBrushVertex*>& vtxlist );

	static void CalcTextureBasis(	const SBrushPlane& p, 
																const SBrushCommon::STexInfo& ti, 
																Vec3& u, 
																Vec3& v );

	static void CalcTexCoords(	const SBrushPlane& p, 
															const SBrushCommon::STexInfo& ti, 
															const Vec3& pos, 
															float& tu, float &tv );

	SBrushCommon::VertexFaceIndexType FindLocalVtxIndex( SBrushCommon::VertexFaceIndexType globalidx ) const;

	void	FitTexture( const std::vector<SBrushVertex*>& vlist, float tileU, float tileV );
	void	Invert( const std::vector<SBrushTriangle*>& triangleArray );

	int		GetMemorySize();	

private:

	friend struct SBrush;
	friend class	CBrushSerialize;

	std::vector<SBrushCommon::VertexFaceIndexType>	pointindexlist;
	std::vector<SBrushCommon::VertexFaceIndexType>	triangleidxlist;
	short								matID;
	SBrushCommon::STexInfo		texinfo;
	AABB								boundbox;
	int									selectededge;
	bool								bSelected;
	SBrushPlane					plane;
	Vec3								center;
};

#endif __BRUSHFACE_H__